/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxline.clinicplus.manager.odonto;

import br.com.foxline.clinicplus.entity.*;
import br.com.foxline.clinicplus.entity.odonto.*;
import br.com.foxline.clinicplus.enums.GroupProcedure;
import br.com.foxline.clinicplus.enums.PaymentType;
import br.com.foxline.clinicplus.enums.TypeIncome;
import br.com.foxline.clinicplus.service.*;
import br.com.foxline.clinicplus.service.odonto.DenteService;
import br.com.foxline.clinicplus.service.odonto.FaceDenteService;
import br.com.foxline.clinicplus.service.odonto.OdontogramaService;
import br.com.foxline.clinicplus.util.Base64;
import br.com.foxline.clinicplus.util.Msg;
import java.io.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

/**
 *
 * @author roniere
 */
@ManagedBean
@ViewScoped
public class ManagerOdontograma implements Serializable {

    @EJB
    RecordsService recordsService;
    @EJB
    SystemUserService systemUserService;
    @EJB
    DiaryService diaryService;
    @EJB
    IncomeService incomeService;
    @EJB
    OdontogramaService odontogramaService;
    @EJB
    DenteService denteService;
    @EJB
    ProcedureService procedureService;
    @EJB
    FaceDenteService faceDenteService;
    @EJB
    CustomerService customerService;
    private PaymentType paymentType;
    private Odontograma odontograma;
    private Dente dente;
    private String teste;
    private List<Dente> inferiores;
    private List<Dente> superiores;
    private TipoDente tipoDente;
    private Procedure procedure;
    private Procedure procedureSearch;
    private Procedure procedureSelect;
    private int codDente;
    private int ateCodDente;
    private boolean ausente = false;
    private Tratamento tratamento;
    private StatusTratamento statusTratamento;
    private List<FaceDente> selectFaceDentes;
    private List<FaceDente> faceDentes;
    private String query;
    private List<Procedure> procedures;
    private List<Dente> dentes;
    private Operator operator;
    private Customer customer;
    private String imagem;
    private Dente denteGeral;
    private Diary diary;
    private Income income;
    private List<Income> incomes;
    private List<Odontograma> odontogramas;

    @PostConstruct
    public void init() {
        Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();

        dentes = new ArrayList<Dente>();
        denteGeral = new Dente();
        denteGeral.setCodigo(0);

        income = new Income();
        income.setCreateAt(new Date());

        inferiores = denteService.preencherInferiores(false);
        superiores = denteService.preencherSuperiores(false);
        procedureSearch = new Procedure();
        odontograma = new Odontograma();
        incomes = new ArrayList<Income>();


        faceDentes = faceDenteService.findAll();

        if (params.get("dw") != null || params.get("r") != null || params.get("o") != null) {
            try {

                if (params.get("dw") != null) {
                    diary = diaryService.find(Long.parseLong(params.get("dw")));
                } else if (params.get("r") != null) {
                    diary = recordsService.getDiaryRecords(Long.parseLong(params.get("r")));
                } else if (params.get("o") != null) {
                    odontograma = odontogramaService.find(Long.parseLong(params.get("o")));
                    if (diary == null) {
                        diary = odontogramaService.getDiaryPorOdontograma(odontograma);
                    }
                }

                if (diary.getRecords() != null) {
                    odontograma = diary.getRecords().getOdontograma();
                }

                customer = diary.getCustomer();

                if (odontograma == null) {
                    odontograma = new Odontograma();
                } else {
                    dentes = odontograma.getDentes();

                    if (dentes == null) {
                        dentes = new ArrayList<Dente>();
                    }

                    for (Dente d : dentes) {
                        for (Dente sup : superiores) {
                            if (d.getCodigo() == sup.getCodigo()) {
                                superiores.set(superiores.indexOf(sup), d);
                                System.err.println(sup);
                                break;
                            }
                        }
                        for (Dente inf : inferiores) {
                            if (d.getCodigo() == inf.getCodigo()) {
                                inferiores.set(inferiores.indexOf(inf), d);
                                break;
                            }
                        }
                    }
                    incomes = odontograma.getIncomes();
                    if (incomes == null) {
                        incomes = new ArrayList<Income>();
                    }
                }

                odontogramas = odontogramaService.getOdontogramaPorPaciente(customer);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void addLancamento() {
        income.setTypeIncome(TypeIncome.C);
        income.setDiary(diary);
        income.setProcedure(this.diary.getProcedure());
        income.setTotalAmount(income.getAmount());
        income.setAmountPaid(income.getAmount());
        income.setDoctor(diary.getDoctor());
        income.setPaymentType(paymentType);

        if (diary.getOperator() != null && !diary.getOperator().getFaturamentoImediato()) {
            income.setFaturamentoImediato(false);
            income.setCompensado(false);
            income.setAmountPaid(BigDecimal.ZERO);
            income.setDataCompensacao(null);
            income.setResponsavelCompensacao(null);

        } else {
            income.setFaturamentoImediato(true);
            income.setCompensado(true);
            income.setDataCompensacao(new Date());
            income.setResponsavelCompensacao(systemUserService.getCurrentUser());
        }


        if (income.getProcedure() != null && (diary != null && diary.getProcedure() != null && diary.getOperator() != null)) {
            incomes.add(income);
        }

        income = new Income();
        income.setCreateAt(new Date());
    }

    public void concluir() {
        try {
            odontograma.setDenticao(tipoDente);
            odontograma.setImagem(imagem);
            odontograma.setDentes(dentes);

            if (odontograma.getId() == null) {

                for (Income i : incomes) {
                    if (i.getId() == null) {
                        incomeService.save(i);
                        if (odontograma.getIncomes() == null) {
                            odontograma.setIncomes(new ArrayList<Income>());
                        }
                        odontograma.getIncomes().add(i);
                    }
                }

                odontograma.setDataCriacao(new Date());

                odontogramaService.save(odontograma);

                if (diary.getRecords() != null) {
                    diary.getRecords().setOdontograma(odontograma);
                    recordsService.update(diary.getRecords());
                }



            } else {

                if (odontograma.getIncomes() == null) {
                    odontograma.setIncomes(new ArrayList<Income>());
                }

                for (Income i : incomes) {
                    if (i.getId() == null) {
                        incomeService.save(i);
                    }
                }

                odontograma.setIncomes(incomes);

                odontogramaService.update(odontograma);
            }

            Msg.messagemInfo();
        } catch (Exception e) {
            e.printStackTrace();
            Msg.messagemError();
        }
    }

    public String getTeste() {
        return teste;
    }

    public void setTeste(String teste) {
        this.teste = teste;
    }

    public List<Dente> getInferiores() {
        return inferiores;
    }

    public void setInferiores(List<Dente> inferiores) {
        this.inferiores = inferiores;
    }

    public List<Dente> getSuperiores() {
        return superiores;
    }

    public void setSuperiores(List<Dente> superiores) {
        this.superiores = superiores;
    }

    public List<SelectItem> tiposDentes() {
        List<SelectItem> itens = new ArrayList<SelectItem>();
        for (TipoDente tipo : TipoDente.values()) {
            itens.add(new SelectItem(tipo, tipo.getDescricao()));
        }
        return itens;
    }

    public List<SelectItem> statusTratamento() {
        List<SelectItem> itens = new ArrayList<SelectItem>();
        for (StatusTratamento st : StatusTratamento.values()) {
            itens.add(new SelectItem(st, st.getNome()));
        }
        return itens;
    }

    public TipoDente getTipoDente() {
        return tipoDente;
    }

    public void setTipoDente(TipoDente tipoDente) {
        this.tipoDente = tipoDente;
    }

    public Procedure getProcedure() {
        return procedure;
    }

    public void setProcedure(Procedure procedure) {
        this.procedure = procedure;
    }

    public int getCodDente() {
        return codDente;
    }

    public void setCodDente(int codDente) {
        this.codDente = codDente;
    }

    public int getAteCodDente() {
        return ateCodDente;
    }

    public void setAteCodDente(int ateCodDente) {
        this.ateCodDente = ateCodDente;
    }

    public boolean isAusente() {
        return ausente;
    }

    public void setAusente(boolean ausente) {
        this.ausente = ausente;
    }

    public StatusTratamento getStatusTratamento() {
        return statusTratamento;
    }

    public void setStatusTratamento(StatusTratamento statusTratamento) {
        this.statusTratamento = statusTratamento;
    }

    public void reinit() {
        tipoDente = TipoDente.PERMANENTE;
        ausente = false;
    }

    public void listProcedure() {
        procedures = procedureService.findProcedure(procedureSearch, true);
    }

    public void addProcedimentoDente() {


        boolean issup = false;
        Dente obj = null;

        if (procedure != null && procedure.getAplicadoTodaArcada()) {

            if (this.tratamento == null) {
                tratamento = new Tratamento();
            }

            tratamento.setProcedimentos(procedure);
            tratamento.setStatusTratamento(statusTratamento);

            if (statusTratamento != null && statusTratamento == StatusTratamento.A_REALIZAR) {
                tratamento.setValor(valorTratamentoPorProcedimento(procedure));
            } else if (tratamento.getId() == null) {
                tratamento.setValor(BigDecimal.ZERO);
            }

            if (denteGeral.getTratamentos() == null) {
                denteGeral.setTratamentos(new ArrayList<Tratamento>());
            }

            if (!denteGeral.getTratamentos().contains(tratamento)) {
                denteGeral.getTratamentos().add(tratamento);
            }

            if (!dentes.contains(denteGeral)) {
                dentes.add(denteGeral);
            }


            return;
        }

        for (int cod = codDente; cod <= ateCodDente; cod++) {
            for (Dente sup : superiores) {

                if (sup.getCodigo() == cod) {
                    issup = true;
                    if (tratamento == null) {
                        tratamento = new Tratamento();
                    }
                    tratamento.setProcedimentos(procedure);
                    tratamento.setFaceDente(selectFaceDentes);
                    tratamento.setStatusTratamento(statusTratamento);

                    if (statusTratamento != null && statusTratamento == StatusTratamento.A_REALIZAR) {
                        tratamento.setValor(valorTratamentoPorProcedimento(procedure));
                    } else if (tratamento.getId() == null) {
                        tratamento.setValor(BigDecimal.ZERO);
                    }

                    if (sup.getTratamentos() == null) {
                        sup.setTratamentos(new ArrayList<Tratamento>());
                    }

                    if (!sup.getTratamentos().contains(tratamento)) {
                        sup.getTratamentos().add(tratamento);
                    }

                    if (!dentes.contains(sup)) {
                        dentes.add(sup);
                    }
                    tratamento = null;

                    break;
                }

            }


            if (!issup) {

                for (Dente inf : inferiores) {

                    if (inf.getCodigo() == cod) {
                        issup = true;

                        if (tratamento == null) {
                            tratamento = new Tratamento();
                        }

                        tratamento.setProcedimentos(procedure);
                        tratamento.setFaceDente(selectFaceDentes);
                        tratamento.setStatusTratamento(statusTratamento);

                        if (statusTratamento != null && statusTratamento == StatusTratamento.A_REALIZAR) {
                            tratamento.setValor(valorTratamentoPorProcedimento(procedure));
                        } else if (tratamento.getId() == null) {
                            tratamento.setValor(BigDecimal.ZERO);
                        }
                        if (inf.getTratamentos() == null) {
                            inf.setTratamentos(new ArrayList<Tratamento>());
                        }

                        if (!inf.getTratamentos().contains(tratamento)) {
                            inf.getTratamentos().add(tratamento);
                        }

                        if (!dentes.contains(inf)) {
                            dentes.add(inf);
                        }

                        tratamento = null;
                        break;
                    }
                }
            }
        }

        procedure = new Procedure();
    }

    public void addConfiguracaoDente() {
        Integer deciduo = null;
        boolean existe = true;
        for (int i = codDente; i <= ateCodDente; i++) {

            if (tipoDente == TipoDente.DECIDUO) {
                deciduo = denteService.getDeciduo(i);
                if (deciduo == null) {
                    existe = false;
                }
            } else {
                tipoDente = TipoDente.PERMANENTE;
                deciduo = null;
                existe = true;
            }

            boolean issup = false;
            for (Dente sup : superiores) {
                if (sup.getCodigo() == i) {

                    sup.setExiste(existe);
                    if (deciduo != null) {
                        sup.setCodigo(deciduo);
                        sup.setTipoDente(TipoDente.DECIDUO);
                        issup = true;
                    } else {
                        sup.setCodigo(denteService.getPermanente(sup.getCodigo()));
                        sup.setTipoDente(TipoDente.PERMANENTE);
                    }
                    sup.setAusente(ausente);

                    break;
                }
            }

            if (!issup) {
                for (Dente inf : inferiores) {
                    if (inf.getCodigo() == i) {
                        inf.setExiste(existe);
                        if (deciduo != null) {
                            inf.setCodigo(deciduo);
                            inf.setTipoDente(TipoDente.DECIDUO);
                        } else {
                            inf.setCodigo(denteService.getPermanente(inf.getCodigo()));
                            inf.setTipoDente(TipoDente.PERMANENTE);
                        }
                        inf.setAusente(ausente);
                        break;
                    }
                }
            }

        }

        reinit();
    }

    public Dente getDente() {
        return dente;
    }

    public void setDente(Dente dente) {
        this.dente = dente;
    }

    public List<FaceDente> getFaceDentes() {
        return faceDentes;
    }

    public void setFaceDentes(List<FaceDente> faceDentes) {
        this.faceDentes = faceDentes;
    }

    public Odontograma getOdontograma() {
        return odontograma;
    }

    public void setOdontograma(Odontograma odontograma) {
        this.odontograma = odontograma;
    }

    public List<FaceDente> getSelectFaceDentes() {
        return selectFaceDentes;
    }

    public void setSelectFaceDentes(List<FaceDente> selectFaceDentes) {
        this.selectFaceDentes = selectFaceDentes;
    }

    public Tratamento getTratamento() {
        return tratamento;
    }

    public void setTratamento(Tratamento tratamento) {
        this.tratamento = tratamento;
    }

    public void selectProcedureDialog() {
        procedure = procedureSelect;
    }

    public Procedure getProcedureSearch() {
        return procedureSearch;
    }

    public void setProcedureSearch(Procedure procedureSearch) {
        this.procedureSearch = procedureSearch;
    }

    public Procedure getProcedureSelect() {
        return procedureSelect;
    }

    public void setProcedureSelect(Procedure procedureSelect) {
        this.procedureSelect = procedureSelect;
    }

    public List<Procedure> getProcedures() {
        return procedures;
    }

    public void setProcedures(List<Procedure> procedures) {
        this.procedures = procedures;
    }

    public List<Dente> getDentes() {
        return dentes;
    }

    public void setDentes(List<Dente> dentes) {
        this.dentes = dentes;
    }

    public void classficacaoDente() {
        Integer deciduo = null;
        Integer permanente = null;

        for (Dente sup : superiores) {

            if (tipoDente == TipoDente.DECIDUO) {
                deciduo = denteService.getDeciduo(sup.getCodigo());
                if (deciduo != null) {
                    sup.setCodigo(deciduo);
                } else {
                    sup.setExiste(false);
                }
            } else if (tipoDente == TipoDente.PERMANENTE) {
                sup.setExiste(true);
                permanente = denteService.getPermanente(sup.getCodigo());
                if (permanente != null) {
                    sup.setCodigo(permanente);
                }
            }
        }

        for (Dente inf : inferiores) {
            if (tipoDente == TipoDente.DECIDUO) {
                deciduo = denteService.getDeciduo(inf.getCodigo());
                if (deciduo != null) {
                    inf.setCodigo(deciduo);
                } else {
                    inf.setExiste(false);
                }
            } else if (tipoDente == TipoDente.PERMANENTE) {
                inf.setExiste(true);
                permanente = denteService.getPermanente(inf.getCodigo());
                if (permanente != null) {
                    inf.setCodigo(permanente);
                }
            }
        }

    }

    public void reloadOpcoes() {

        int[] sup = denteService.getSuperiores();
        int[] inf = denteService.getInferiores();

        for (Dente d : superiores) {
            if (d.getCodigo() == codDente) {
                tipoDente = d.getTipoDente();
                ausente = d.isAusente();
                break;
            }
        }
        for (Dente d : inferiores) {
            if (d.getCodigo() == codDente) {
                tipoDente = d.getTipoDente();
                ausente = d.isAusente();
                break;
            }
        }
    }

    public BigDecimal valorTratamentoPorDente(Dente d) {
        BigDecimal v = BigDecimal.ZERO;

        for (Tratamento t : d.getTratamentos()) {
            if (t.getStatusTratamento() == statusTratamento.A_REALIZAR) {
                v = v.add(procedureService.getValueProcedureOperator(t.getProcedimentos(), operator));
            }
        }

        return v;
    }

    public BigDecimal valorTratamentoPorProcedimento(Procedure p) {
        BigDecimal v = BigDecimal.ZERO;
        v = v.add(procedureService.getValueProcedureOperator(p, operator));
        return v;
    }

    public BigDecimal totalValorTratamento() {
        BigDecimal v = BigDecimal.ZERO;

        if (dentes != null) {
            for (Dente d : dentes) {
                for (Tratamento t : d.getTratamentos()) {
                    if (t.getStatusTratamento() == StatusTratamento.A_REALIZAR) {
                        v = v.add(procedureService.getValueProcedureOperator(t.getProcedimentos(), operator));
                    }
                }
            }
        }

        return v;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public int getAge() {
        int idade = 0;
        if (customer != null && customer.getDateBirth() != null) {
            Calendar c = new GregorianCalendar();
            Calendar dateBirth = new GregorianCalendar();
            dateBirth.setTime(customer.getDateBirth());

            idade = c.get(Calendar.YEAR) - dateBirth.get(Calendar.YEAR);

            dateBirth.add(Calendar.YEAR, idade);

            if (c.before(dateBirth)) {
                idade--;
            }
        }
        return idade;

    }

    public String getImagem() {
        return imagem;
    }

    public void setImagem(String imagem) {
        this.imagem = imagem;
    }

    private void gravarArquivo(String caminho, byte[] arquivo) {
        if (arquivo != null) {
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(caminho);
                fos.write(arquivo);
                fos.close();
            } catch (FileNotFoundException ex) {
                System.err.println(ex);
            } catch (IOException ex1) {
                System.err.println(ex1);
            } finally {
                try {
                    fos.close();
                } catch (IOException ex2) {
                    System.err.println(ex2);
                }
            }
        }
    }

    public void print() {
        try {
            byte[] decode = Base64.decode(imagem);

            SimpleDateFormat sdf = new SimpleDateFormat("hh-mm-ss");

            gravarArquivo("/tmp/teste" + sdf.format(new Date()) + ".png", decode);
            InputStream i = new ByteArrayInputStream(decode);

            odontograma.setDentes(dentes);
            odontograma.setImagemRelatorio(i);
            imagem = null;
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    public void gera() {
        List<Odontograma> lst = new ArrayList<Odontograma>();
        lst.add(odontograma);

        HashMap<String, Object> param = new HashMap<String, Object>();
        if (customer != null) {
            param.put("name", customer.getName());
            param.put("gender.name", customer.getGender() != null ? customer.getGender().getName() : "");
            param.put("cpf", customer.getCpf());
            param.put("rg", customer.getRg());
            param.put("phone", customer.getPhone());
            param.put("operator.name", customer.getOperator() != null ? customer.getOperator().getName() : "");
            param.put("idade", customer.getDateBirth() != null ? getAge(customer.getDateBirth()) + "" : "");
            param.put("total", totalValorTratamento());
        }
        odontogramaService.relatorioOdontograma(param, lst);
    }

    public int getAge(Date data) {
        int idade = 0;
        if (data != null) {
            Calendar c = new GregorianCalendar();
            Calendar dateBirth = new GregorianCalendar();
            dateBirth.setTime(data);

            idade = c.get(Calendar.YEAR) - dateBirth.get(Calendar.YEAR);

            dateBirth.add(Calendar.YEAR, idade);

            if (c.before(dateBirth)) {
                idade--;
            }
        }
        return idade;

    }

    public void remover(int id1, int id) {
        Dente dente = dentes.get(id1);

        if (dente.getTratamentos() != null) {
            dente.getTratamentos().remove(id);
        }

        if (dente.getTratamentos() == null || dente.getTratamentos().isEmpty()) {
            dentes.remove(id);
        }

    }

    public void visualizarProcedimento(int id1, int id) {

        dente = dentes.get(id1);
        tratamento = dente.getTratamentos().get(id);

        if (tratamento != null) {
            procedure = tratamento.getProcedimentos();
            codDente = dente.getCodigo();
            ateCodDente = dente.getCodigo();
            selectFaceDentes = tratamento.getFaceDente();
        }


    }

    public Dente getDenteGeral() {
        return denteGeral;
    }

    public void setDenteGeral(Dente denteGeral) {
        this.denteGeral = denteGeral;
    }

    public Income getIncome() {
        return income;
    }

    public void setIncome(Income income) {
        this.income = income;
    }

    public List<Income> getIncomes() {
        return incomes;
    }

    public void setIncomes(List<Income> incomes) {
        this.incomes = incomes;
    }

    public List<Odontograma> getOdontogramas() {
        return odontogramas;
    }

    public void setOdontogramas(List<Odontograma> odontogramas) {
        this.odontogramas = odontogramas;
    }

    public PaymentType getPaymentType() {
        return paymentType;
    }

    public void setPaymentType(PaymentType paymentType) {
        this.paymentType = paymentType;
    }

    public List<SelectItem> selectPaymentType() {
        List<SelectItem> paymentTypes = new ArrayList<SelectItem>();
        for (PaymentType ms : PaymentType.values()) {
            paymentTypes.add(new SelectItem(ms, ms.getName()));
        }
        return paymentTypes;
    }
}
//        FaceDente fd = new FaceDente("L", "Lingual");
//        fd = new FaceDente("D", "Distal");
//        faceDenteService.save(fd);
//        fd = new FaceDente("M", "Mesial");
//        faceDenteService.save(fd);
//        fd = new FaceDente("O", "Oclusal");
//        faceDenteService.save(fd);
//        fd = new FaceDente("V", "Vestibular");
//        faceDenteService.save(fd);
//        fd = new FaceDente("L", "Lingual");
//        faceDenteService.save(fd);
//        fd = new FaceDente("P", "Palatal");
//        faceDenteService.save(fd);
